package com.zhouchao.transfer.utils;

import com.zhouchao.transfer.Constants;
import com.zhouchao.transfer.factory.BeanFactory;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @Author: zhouchao
 * @Date: 2021/05/23 22:56
 * @Description:
 */
public class ScanUtil {
    private final static  String classpath = ScanUtil.class.getResource("/").getPath();

    public static Set<String> scanPackage(String basePackage) {
        String path = StringUtils.replace(basePackage, ".", File.separator);
        Enumeration<URL> resourceUrls = null;
        Set<String> files = null;
        try {
            resourceUrls = BeanFactory.class.getClassLoader().getResources(path);
            URL url = resourceUrls.nextElement();
            String protocol = url.getProtocol();
            if ("jar".equalsIgnoreCase(protocol)){
                //转换为JarURLConnection
                JarURLConnection connection = (JarURLConnection) url.openConnection();
                if (connection != null) {
                    JarFile jarFile = connection.getJarFile();
                    if (jarFile != null) {
                        //得到该jar文件下面的类实体
                        Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
                        while (jarEntryEnumeration.hasMoreElements()) {
                            /*entry的结果大概是这样：
                                    org/
                                    org/junit/
                                    org/junit/rules/
                                    org/junit/runners/*/
                            JarEntry entry = jarEntryEnumeration.nextElement();
                            String jarEntryName = entry.getName();
                            //这里我们需要过滤不是class文件和不在basePack包名下的类
                            if (jarEntryName.contains(".class") && jarEntryName.replaceAll("/",".").startsWith(basePackage)) {
                                String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replace("/", ".");
                                files.add(className);
                            }
                        }
                    }
                }
            }else {
                resourceUrls = BeanFactory.class.getClassLoader().getResources(path);
                URI uri = new URI(StringUtils.replace(resourceUrls.nextElement().toString(), " ", "%20"));
                File file = new File(uri.getSchemeSpecificPart());
                files = scanFile(file, new HashSet<>());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return files;
    }

    private static Set<String> scanFile(File file, Set<String> fileSet) {
        if (file == null) return null;
        File[] files = file.listFiles();
        if (files == null || files.length == 0) return null;
        for (File f : files) {
            if (f.isDirectory()) {
                scanFile(f, fileSet);
            } else {
                String s = f.getPath().replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");
                fileSet.add(s);
            }
        }
        return fileSet;
    }

    public static void main(String[] args) {
        String url = Constants.CLASSPATH_ALL_URL_PREFIX;
        Set<String> fileSet = scanPackage(url);
        fileSet.forEach(System.out::println);
    }
}
